﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FeiraGame_XNA.src.core.manager;

namespace FeiraGame_XNA.src.core
{
    public class InterfaceObject
    {
        #region Variables
        public bool isAlive { get; protected set; }
        public struct Animation
        {
            public int Width { get; set; }              // Largura da imagem
            public int Height { get; set; }             // Altura da imagem
            public int Frames { get; set; }              // Quantidade de imagens
            public int Fps { get; set; }   // Quantidade de imagens por segundo
            public int Y { get; set; }                   // Linha da spritesheet
            public string Name { get; set; }             // Nome da animação
        }
        public Animation anim;
        public Animation Anim
        {
            get { return anim; }
            set { anim = value; }
        }
        
        protected bool visible;
        public bool Visible
        {
            get { return visible; }
            set { visible = value; }
        }

        protected Rectangle colisionBox;
        public Rectangle ColisionBox
        {
            get { return colisionBox; }
            protected set { colisionBox = value; }
        }

        protected float scrollSpeed;
        public float ScrollSpeed
        {
            get { return scrollSpeed; }
            protected set { scrollSpeed = value; }
        }

        protected Vector2 position;
        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        protected Texture2D texture;
        public Texture2D Texture
        {
            get { return texture; }
            protected set { texture = value; }
        }

        protected Vector2 speed;               //Velocidade
        public Vector2 Speed
        {
            get { return speed; }
            protected set { speed = value; }
        }

        protected bool moving;                    //Diz se o objeto está se movendo
        protected bool Moving
        {
            get { return moving; }
            set { moving = value; }
        }

        public bool FacingRight { get; protected set; }            //Diz para que direção o sprite está virado
        protected Rectangle imageData;         //Dados da imagem que será exibida na tela do jogo
        protected Rectangle spriteImage;       //Posição da imagem na spritesheet
        public float Alpha { get; protected set; }                           //Transparência da imagem
        protected Color spriteColor;           //Máscara de cor que será aplicada na imagem
        protected float rotation;              //Rotação da imagem
        protected Vector2 rotation_point;      //Ponto em que a imagem sofrerá rotação
        protected SpriteEffects effects;       //Realizar o flip da imagem (horizontal ou vertical)
        protected float Depth { get; set; }                 //Profundidade

        protected float scale;
        public float Scale
        {
            get { return scale; }
            set { scale = value; }
        }

        protected List<Animation> animations;  //Lista de animações
        protected int currentAnimationIndex;   //Index da animação atual
        #endregion 


        /// <summary>
        ///Básico construtor que seta todos os valores básicos sem imagem. Basic Constructor With set all Basic Values without texture.
        /// </summary>
        #region InterfaceObjet
        public InterfaceObject()
        {
            ColisionBox = new Rectangle();
            ScrollSpeed = 0;
            Position = Vector2.Zero;
            this.Visible = true;
            this.Alpha = 1.0f;
            this.spriteColor = new Color(1.0f * Alpha, 1.0f * Alpha, 1.0f * Alpha);
            this.rotation = 0f;
            this.rotation_point = Vector2.Zero;
            this.Depth = 0f;
            this.FacingRight = true;          
            this.Moving = false;
            this.animations = new List<Animation>();
            Initialize();
            //this.currentAnimationIndex = 0;
        }
        #endregion

        /// <summary>
        /// Constructor with texture
        /// </summary>
        /// <param name="texture"></param>
        #region InterfaceObject 2 with Texture
        public InterfaceObject(Texture2D texture)
        {
            this.Texture = texture;
            this.animations = new List<Animation>();
            this.visible = true;
            this.spriteColor = new Color(1.0f * Alpha, 1.0f * Alpha, 1.0f * Alpha);
            this.rotation = 0f;
            this.rotation_point = Vector2.Zero;
            this.scale = 1.0f;
            this.Depth = 0f;
            this.FacingRight = true;
            Initialize();

        }//InterfaceObject
        #endregion

        /// <summary>
        /// Initialize Base
        /// </summary>
        #region Initialize
        public virtual void Initialize()
        {
            if (Scale == 0)
                Scale = 1;
            if (Alpha < 0)
                Alpha = 1;
        }
        #endregion

        /// <summary>
        /// O que fazer quando clicar o objeto. How to do when clicked.
        /// </summary>
        #region OnClick
        public virtual void OnClick()
        {

        }
        #endregion

        /// <summary>
        /// O que fazer quando o mouse ficar sob o objeto. How to do when mouse Over.
        /// </summary>
        #region MouseOver
        public virtual void MouseOver()
        {

        }
        #endregion

        /// <summary>
        /// Atribui para a animação de tal Número. Set a Animation by Index ( int )
        /// </summary>
        /// <param name="index">Número da Animação. Number of Animation</param>
        #region SetAnimationIndex
        public void setAnimationIndex(int index)
        {
            this.currentAnimationIndex = index;
        }
        #endregion

        /// <summary>
        /// Pega o index da animação atual. Return the index of current Animation
        /// </summary>
        /// <returns>O Número da animação Atual. The Index Number</returns>
        #region GetAnimationIndex
        public int getAnimationIndex()
        {
            return currentAnimationIndex;
        }
        #endregion

        /// <summary>
        /// Pega a animação atual. Get the Current Animation
        /// </summary>
        /// <returns>A Animação Atual. The Current Animation</returns>
        #region GetAnimation
        public Animation getAnimation()
        {
            return animations.ElementAt(currentAnimationIndex);
        }
        #endregion

        /// <summary>
        /// Base Update
        /// </summary>
        #region Update
        public virtual void Update()
        {
            if(Inputs.MouseOver(this))
                MouseOver();
            if(Inputs.checkClick(this))
                OnClick();

            ColisionBox = new Rectangle((int)this.Position.X, (int)this.Position.Y, (int)(this.getAnimation().Width * Scale), (int)(this.getAnimation().Height * Scale));
        }
        #endregion

        /// <summary>
        /// Desenho básico SEM animãção . Basic Draw WITHOUT Animation
        /// </summary>
        /// <param name="spriteBatch">SpriteBatch</param>
        #region Basic Draw
        public void Draw(SpriteBatch spriteBatch)
        {
            if (!visible)
                return;

            spriteBatch.Draw(this.texture, this.position, Color.White);
            
        }
        #endregion

        /// <summary>
        /// Desenho básico COM animãção . Basic Draw WITH Animation
        /// </summary>
        /// <param name="gameTime">Tempo de jogo. GameTime</param>
        /// <param name="spriteBatch">SpriteBatch</param>
        /// <param name="animating">Se é animável ou não. Can be Animate or not</param>
        #region Draw With Animation
        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch, Boolean animating)
        {
            if (!visible)
                return;
            Animation anim = this.getAnimation(); //Pega a animação atual

            int current_frame = (int)(gameTime.TotalGameTime.TotalSeconds * anim.Fps) % anim.Frames; //Frame atual

            imageData = new Rectangle((int)position.X, (int)position.Y, anim.Width, anim.Height); // Posição na tela
            spriteImage = new Rectangle(current_frame * anim.Width, anim.Y * anim.Height, anim.Width, anim.Height); // Posição na spritesheet
            
            effects = ((FacingRight) ? SpriteEffects.None : SpriteEffects.FlipHorizontally);  //Devemos espelhar a imagem?

            //spriteBatch.Draw(texture, imageData, spriteImage, spriteColor, rotation, rotation_point, Scale, effects, Depth);
            spriteColor = new Color(spriteColor.R * Alpha, spriteColor.G * Alpha, spriteColor.B * Alpha);
            spriteBatch.Draw(Texture, Position, spriteImage, spriteColor, rotation, rotation_point, Scale, effects, Depth);
        }
        #endregion

        
        /// <summary>
        /// Função de destruir o objeto. Function For destroy
        /// </summary>
        #region Destroy
        public virtual void Destroy()
        {
            this.isAlive = false;

        }
        #endregion

    }
}
